VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "Api"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

'==================
' local constants
'==================
Const STR_CONNECTION_CLOSED = "Connection to TWS is closed"

' data members
Private WithEvents m_Tws As TWSLib.Tws
Attribute m_Tws.VB_VarHelpID = -1
Private m_orderId As Long

'===============
' constructor
'===============
Private Sub Class_Initialize()
    Set m_Tws = New TWSLib.Tws
   
    General.SetDisconnected
End Sub

'===============
' destructor
'===============
Private Sub Class_Terminate()
    Set m_Tws = Nothing
End Sub

Public Property Get Tws() As TWSLib.Tws
Set Tws = m_Tws
End Property

Public Property Get NextOrderId() As Long
NextOrderId = m_orderId
m_orderId = m_orderId + 1
End Property


'=======================================
' TWS Control - Events generated by ActiveX TWS control
'=======================================
' connection closed
Private Sub m_Tws_connectionClosed()
    General.SetDisconnected
End Sub

' error
Private Sub m_Tws_errMsg(ByVal id As Long, ByVal errorCode As Long, ByVal errorMsg As String)
    On Error Resume Next
   
    ' log error message
    Log.LogMessage id, errorCode, errorMsg
    
    If errorCode = 504 Then
        ' not connected
        General.SetDisconnected
    ElseIf id >= ORDER_ID_BASE Then
        BasicOrders.ProcessError id, errorCode, errorMsg
        ConditionalOrders.ProcessError id, errorCode, errorMsg
        AdvancedOrders.ProcessError id, errorCode, errorMsg
        Advisors.ProcessError id, errorCode, errorMsg
    End If
    
    Select Case id
        Case ID_TICKERS To ID_TICKERS + ID_GAP - 1
            Tickers.ProcessError id, errorCode, errorMsg
            
        Case ID_PORTFOLIO To ID_PORTFOLIO + ID_GAP - 1
            Portfolio.ProcessError id, errorCode, errorMsg
        
        Case ID_MKTDEPTH To ID_MKTDEPTH + ID_GAP - 1
            If errorCode <> 2152 Then
                MarketDepth.ProcessError id, errorCode, errorMsg
            End If
        Case ID_HISTDATA To ID_HISTDATA + ID_GAP - 1
            HistoricalData.ProcessError id, errorCode, errorMsg
        
        Case ID_CONTRACTDETAILS To ID_CONTRACTDETAILS + ID_GAP - 1
            ContractDetails.ProcessError id, errorCode, errorMsg
        
        Case ID_BONDCONTRACTDETAILS To ID_BONDCONTRACTDETAILS + ID_GAP - 1
            BondContractDetails.ProcessError id, errorCode, errorMsg
        
        Case ID_REALTIMEBARS To ID_REALTIMEBARS + ID_GAP - 1
            RealTimeBars.ProcessError id, errorCode, errorMsg
        
        Case ID_MARKETSCANNER To ID_MARKETSCANNER + ID_GAP - 1
            MarketScanner.ProcessError id, errorCode, errorMsg
        
        Case ID_FUNDAMENTALS To ID_FUNDAMENTALRATIOS + ID_GAP - 1
            Fundamentals.ProcessError id, errorCode, errorMsg
            
        Case ID_CALC_IMPL_VOL To ID_CALC_IMPL_VOL + ID_GAP - 1
            Tickers.ProcessError id, errorCode, errorMsg
            
        Case ID_CALC_OPTION_PRICE To ID_CALC_OPTION_PRICE + ID_GAP - 1
            Tickers.ProcessError id, errorCode, errorMsg
            
        Case ID_TICKBYTICKDATA To ID_TICKBYTICKDATA + ID_GAP - 1
            TickByTick.ProcessError id, errorCode, errorMsg
            
        Case Else
            If General.ShowErrorsMsgBoxChk.value Then
                MsgBox "Error" & Chr(13) & "id: " & id & Chr(13) & "errorCode: " & errorCode & Chr(13) _
                        & "errorMsg: " & errorMsg
            End If
    
    End Select
End Sub


Private Sub m_Tws_headTimestamp(ByVal reqId As Long, ByVal timeStamp As String)
    On Error Resume Next
    HeadTimestamp.UpdateHeadTimestamp reqId, timeStamp
End Sub

Private Sub m_Tws_histogramData(ByVal reqId As Long, ByVal data As TWSLib.IHistogramEntry)
    On Error Resume Next
    Histogram.UpdateHistogramData reqId, data.price, data.size
End Sub

Private Sub m_Tws_historicalDataEnd(ByVal reqId As Long, ByVal startDate As String, ByVal endDate As String)
    On Error Resume Next
    HistoricalData.FinishUpdateHistoricalData reqId, startDate, endDate
End Sub

Private Sub m_Tws_historicalNews(ByVal requestId As Long, ByVal time As String, ByVal providerCode As String, ByVal articleId As String, ByVal headline As String)
    News.HistoricalNews requestId, time, providerCode, articleId, headline
End Sub

Private Sub m_Tws_historicalNewsEnd(ByVal requestId As Long, ByVal hasMore As Boolean)
    News.HistoricalNewsEnd requestId, hasMore
End Sub

' market data type responce
Private Sub m_Tws_marketDataType(ByVal reqId As Long, ByVal marketDataType As Long)
    On Error Resume Next
    Tickers.UpdateMarketDataType reqId, marketDataType
End Sub

Private Sub m_Tws_newsArticle(ByVal requestId As Long, ByVal articleType As Long, ByVal articleText As String)
    News.newsArticle requestId, articleType, articleText
End Sub

Private Sub m_Tws_newsProviders(ByVal newsProviders As TWSLib.INewsProviderList)
    News.newsProviders newsProviders
End Sub

' next valid Id
Private Sub m_Tws_nextValidId(ByVal id As Long)
    On Error Resume Next
    General.SetConnected
    If id < ORDER_ID_BASE Then
        m_orderId = ORDER_ID_BASE
    Else
        m_orderId = id
    End If
End Sub


'-----------------------------
' orders events
'-----------------------------
Private Sub m_Tws_orderStatus(ByVal id As Long, ByVal status As String, ByVal filled As Double, ByVal remaining As Double, ByVal avgFillPrice As Double, ByVal permId As Long, ByVal parentId As Long, ByVal lastFillPrice As Double, ByVal clientId As Long, ByVal whyHeld As String, ByVal mktCapPrice As Double)
    On Error Resume Next
    ' update Orders sheet data
        
    If id <> 0 Then
        BasicOrders.UpdateOrderStatus id, status, filled, remaining, avgFillPrice, parentId, lastFillPrice
        ConditionalOrders.UpdateOrderStatus id, status, filled, remaining, avgFillPrice, parentId, lastFillPrice
        AdvancedOrders.UpdateOrderStatus id, status, filled, remaining, avgFillPrice, parentId, lastFillPrice
        Advisors.UpdateOrderStatus id, status, filled, remaining, avgFillPrice, parentId, lastFillPrice
    End If

    On Error Resume Next
    ' update Open Orders sheet data
    OpenOrders.UpdateOrderStatus id, status, filled, remaining, avgFillPrice, parentId, permId, lastFillPrice
End Sub

Private Sub m_Tws_openOrderEx(ByVal orderId As Long, ByVal contract As TWSLib.IContract, ByVal order As TWSLib.IOrder, ByVal orderState As TWSLib.IOrderState)
    On Error Resume Next
    If order.WhatIf Then
        ' update order status (WhatIf) in Basic Orders/Advance Orders sheet
         BasicOrders.UpdateWhatIfInfo orderId, contract, order, orderState
         AdvancedOrders.UpdateWhatIfInfo orderId, contract, order, orderState
         Advisors.UpdateWhatIfInfo orderId, contract, order, orderState
    Else
        ' update Open Orders sheet data
        OpenOrders.UpdateOpenOrder orderId, contract, order, orderState
    End If
End Sub


Private Sub m_Tws_pnl(ByVal reqId As Long, ByVal dailyPnL As Double, ByVal unrealizedPNL As Double, ByVal realizedPNL As Double)
    On Error Resume Next
    AcctUpdMulti.UpdatePnL reqId, dailyPnL, unrealizedPNL, realizedPNL
End Sub

Private Sub m_Tws_pnlSingle(ByVal reqId As Long, ByVal pos As Long, ByVal dailyPnL As Double, ByVal unrealizedPNL As Double, ByVal realizedPNL As Double, ByVal value As Double)
    On Error Resume Next
    AcctUpdMulti.UpdatePnLSingle reqId, pos, dailyPnL, unrealizedPNL, realizedPNL, value
End Sub

Private Sub m_Tws_securityDefinitionOptionParameter(ByVal reqId As Long, ByVal exchange As String, ByVal underlyingConId As Long, ByVal tradingClass As String, ByVal multiplier As String, ByVal expirations As String, ByVal strikes As String)
    On Error Resume Next
    SecDefOptParams.UpdateSecDefOptParams _
        reqId, _
        exchange, _
        underlyingConId, _
        tradingClass, _
        multiplier, _
        expirations, _
        strikes
    
End Sub

Private Sub m_Tws_smartComponents(ByVal reqId As Long, ByVal theMap As TWSLib.IComList)
    Dim i As Long
    Dim component As ISmartComponent
    
    For i = 0 To theMap.Count - 1
        Set component = theMap(i)
        
        SmartComponents.UpdateSmartComponents reqId, component.bitNumber, component.exchange, component.exchangeLetter
    Next
End Sub

Private Sub m_Tws_softDollarTiers(ByVal reqId As Long, ByVal tiers As TWSLib.IComList)
    Dim i As Long
    Dim tier As ISoftDollarTier
    
    For i = 0 To tiers.Count - 1
        Set tier = tiers(i)
        
        SoftDollarTiers.UpdateSoftDollarTiers reqId, tier.name, tier.displayName, tier.value
    Next
End Sub

'-----------------------------
' market data  tickers events
'-----------------------------
Private Sub m_Tws_tickEFP(ByVal tickerId As Long, ByVal field As Long, ByVal basisPoints As Double, ByVal formattedBasisPoints As String, ByVal totalDividends As Double, ByVal holdDays As Long, ByVal futureExpiry As String, ByVal dividendImpact As Double, ByVal dividendsToExpiry As Double)
    'update Tickers sheet with tick EFP
    On Error Resume Next
    Tickers.UpdateTickersSheetWithTickEFP tickerId, field, basisPoints, formattedBasisPoints, totalDividends, holdDays, futureExpiry, dividendImpact, dividendsToExpiry
End Sub

Private Sub m_Tws_tickGeneric(ByVal id As Long, ByVal tickType As Long, ByVal value As Double)
    'update Tickers sheet with tick generic
    On Error Resume Next
    Tickers.UpdateTickersSheetWithTickGeneric id, tickType, value
End Sub

Private Sub m_Tws_tickNews(ByVal tickerId As Long, ByVal timeStamp As String, ByVal providerCode As String, ByVal articleId As String, ByVal headline As String, ByVal extraData As String)
    News.TickNews tickerId, timeStamp, providerCode, articleId, headline, extraData
End Sub

Private Sub m_Tws_tickOptionComputation(ByVal id As Long, ByVal tickType As Long, ByVal impliedVol As Double, ByVal delta As Double, ByVal optPrice As Double, ByVal pvDividend As Double, ByVal gamma As Double, ByVal vega As Double, ByVal theta As Double, ByVal undPrice As Double)
    'update Tickers sheet with new data
    On Error Resume Next
    Tickers.UpdateTickersSheetWithOptionComp id, tickType, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice
End Sub

Private Sub m_Tws_tickPrice(ByVal id As Long, ByVal tickType As Long, ByVal price As Double, ByVal CanAutoExecute As Boolean, ByVal PastLimit As Boolean, ByVal PreOpen As Boolean)
    'update Tickers sheet with new price
    On Error Resume Next
    Tickers.UpdateTickersSheetWithPrice id, tickType, price, CanAutoExecute, PastLimit, PreOpen
End Sub

Private Sub m_Tws_tickSize(ByVal id As Long, ByVal tickType As Long, ByVal size As Long)
    'update Tickers sheet with new size
    On Error Resume Next
    Tickers.UpdateTickersSheetWithSize id, tickType, size
End Sub

Private Sub m_Tws_tickString(ByVal id As Long, ByVal tickType As Long, ByVal value As String)
    'update Tickers sheet with new string
    On Error Resume Next
    If tickType = FUNDAMENTAL_RATIOS Then
        ' fundamental ratios
        Fundamentals.UpdateFundamentalRatios id, tickType, value
    Else
        Tickers.UpdateTickersSheetWithString id, tickType, value
    End If
End Sub

'-----------------------------
' market depth events
'-----------------------------
Private Sub m_Tws_updateMktDepth(ByVal id As Long, ByVal position As Long, ByVal operation As Long, ByVal side As Long, ByVal price As Double, ByVal size As Long)
    ' update Market Depth sheet with new data
    On Error Resume Next
    MarketDepth.UpdateMarketDepth id, position, STR_EMPTY, operation, side, price, size
    
End Sub

Private Sub m_Tws_updateMktDepthL2(ByVal id As Long, ByVal position As Long, ByVal marketMaker As String, ByVal operation As Long, ByVal side As Long, ByVal price As Double, ByVal size As Long, ByVal isSmartDepth As Boolean)
    ' update Market Depth sheet with new data
    On Error Resume Next
    MarketDepth.UpdateMarketDepth id, position, marketMaker, operation, side, price, size
End Sub

'-----------------------------
' news bulletins events
'-----------------------------
Private Sub m_Tws_updateNewsBulletin(ByVal msgId As Integer, ByVal msgType As Integer, ByVal message As String, ByVal origExchange As String)
    ' update News Bulletins page with new data
    On Error Resume Next
    Bulletins.updateNewsBulletins msgId, msgType, message, origExchange
End Sub

'-----------------------------
' accountportfolio events
'-----------------------------
Private Sub m_Tws_managedAccounts(ByVal accountsList As String)
    On Error Resume Next
    Account.UpdateManagedAccounts accountsList
End Sub

Private Sub m_Tws_updateAccountTime(ByVal timeStamp As String)
    On Error Resume Next
    Account.UpdateTimeStamp timeStamp
End Sub

Private Sub m_Tws_updateAccountValue(ByVal key As String, ByVal value As String, ByVal curency As String, ByVal accountName As String)
    On Error Resume Next
    Account.UpdateAccountValue key, value, curency, accountName
End Sub

Private Sub m_Tws_updatePortfolioEx(ByVal contract As TWSLib.IContract, ByVal position As Double, ByVal marketPrice As Double, ByVal marketValue As Double, ByVal averageCost As Double, ByVal unrealizedPNL As Double, ByVal realizedPNL As Double, ByVal accountName As String)
    On Error Resume Next
    Portfolio.UpdatePortfolio contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName
End Sub

'----------------------------
' FA events
'----------------------------
Private Sub m_Tws_receiveFA(ByVal faDataType As Long, ByVal cxml As String)
    On Error Resume Next
    Account.UpdateFA faDataType, cxml
End Sub

'-----------------------------
' execution events
'-----------------------------
Private Sub m_Tws_execDetailsEx(ByVal reqId As Long, ByVal contract As TWSLib.IContract, ByVal execution As TWSLib.IExecution)
    On Error Resume Next
    Executions.UpdateExecution reqId, contract, execution
End Sub

'-----------------------------
' historical data events
'-----------------------------
Private Sub m_Tws_historicalData(ByVal reqId As Long, ByVal histDate As String, ByVal histOpen As Double, ByVal histHigh As Double, ByVal histLow As Double, ByVal histClose As Double, ByVal histVolume As Long, ByVal barCount As Long, ByVal WAP As Double, ByVal hasGaps As Long)
    On Error Resume Next
    HistoricalData.UpdateHistoricalData reqId, histDate, histOpen, histHigh, histLow, histClose, histVolume, barCount, WAP, hasGaps
End Sub

'---------------------------------------
' contractbond contract details events
'---------------------------------------
Private Sub m_Tws_contractDetailsEx(ByVal reqId As Long, ByVal conDetails As TWSLib.IContractDetails)
    On Error Resume Next
    ContractDetails.UpdateContractDetails reqId, conDetails
End Sub

Private Sub m_Tws_bondContractDetailsEx(ByVal reqId As Long, ByVal ContractDetails As TWSLib.IContractDetails)
    On Error Resume Next
    BondContractDetails.UpdateBondContractDetails reqId, ContractDetails
End Sub

Private Sub m_Tws_contractDetailsEnd(ByVal reqId As Long)
    On Error Resume Next
    
    If reqId >= ID_CONTRACTDETAILS And reqId < ID_BONDCONTRACTDETAILS Then
        ContractDetails.ContractDetailsEnd reqId
    ElseIf reqId >= ID_BONDCONTRACTDETAILS And reqId < ID_REALTIMEBARS Then
        BondContractDetails.ContractDetailsEnd reqId
    End If
End Sub

'-----------------------------
' real time bars events
'-----------------------------
Private Sub m_Tws_realtimeBar(ByVal tickerId As Long, ByVal rtbTime As Long, ByVal rtbOpen As Double, ByVal rtbHigh As Double, ByVal rtbLow As Double, ByVal rtbClose As Double, ByVal rtbVolume As Long, ByVal rtbWAP As Double, ByVal rtbCount As Long)
    On Error Resume Next
    RealTimeBars.UpdateRealTimeBars tickerId, rtbTime, rtbOpen, rtbHigh, rtbLow, rtbClose, rtbVolume, rtbWAP, rtbCount
End Sub

'-----------------------------
' current time events
'-----------------------------
Private Sub m_Tws_currentTime(ByVal time As Long)
    On Error Resume Next
    General.UpdateCurrentTime time
End Sub

'-----------------------------
' market scanner events
'-----------------------------
Private Sub m_Tws_scannerParameters(ByVal xml As String)
    On Error Resume Next
    MarketScanner.UpdateScannerParameters xml
End Sub

Private Sub m_Tws_scannerDataEx(ByVal reqId As Long, ByVal rank As Long, ByVal ContractDetails As TWSLib.IContractDetails, ByVal distance As String, ByVal benchmark As String, ByVal projection As String, ByVal legsStr As String)
    On Error Resume Next
    MarketScanner.UpdateScannerData reqId, rank, ContractDetails, distance, benchmark, projection, legsStr
End Sub

Private Sub m_Tws_scannerDataEnd(ByVal reqId As Long)
    On Error Resume Next
    MarketScanner.ScannerDataEnd reqId
End Sub

'-----------------------------
' fundamentals events
'-----------------------------
Private Sub m_Tws_fundamentalData(ByVal reqId As Long, ByVal data As String)
    On Error Resume Next
    Fundamentals.UpdateFundamentalsData reqId, data
End Sub

'-----------------------------
' commission reports
'-----------------------------
Private Sub m_Tws_commissionReport(ByVal commissionReport As TWSLib.ICommissionReport)
    On Error Resume Next
    CommissionReports.UpdateCommissionReports commissionReport
End Sub

'-----------------------------
' account update  multi
'-----------------------------
Private Sub m_Tws_accountUpdateMulti(ByVal requestId As Long, ByVal Account As String, ByVal modelCode As String, ByVal key As String, ByVal value As String, ByVal curency As String)
    On Error Resume Next
    AcctUpdMulti.AccountUpdateMulti requestId, Account, modelCode, key, value, curency
End Sub

'-----------------------------
' positions  multi
'-----------------------------
Private Sub m_Tws_positionMulti(ByVal requestId As Long, ByVal Account As String, ByVal modelCode As String, ByVal contract As TWSLib.IContract, ByVal position As Double, ByVal avgCost As Double)
    On Error Resume Next
    PositionsMulti.PositionMulti requestId, Account, modelCode, contract, position, avgCost
End Sub

'-----------------------------
' family codes
'-----------------------------
Private Sub m_Tws_familyCodes(ByVal famCodes As TWSLib.IFamilyCodeList)
    On Error Resume Next
    FamilyCodes.FamilyCodes famCodes
End Sub

'-----------------------------
' symbol samples
'-----------------------------
Private Sub m_Tws_symbolSamples(ByVal reqId As Long, ByVal contractDescriptions As TWSLib.IContractDescriptionList)
    On Error Resume Next
    SymbolSamples.SymbolSamples reqId, contractDescriptions
End Sub

'-----------------------------
' mkt depth exchanges
'-----------------------------
Private Sub m_Tws_mktDepthExchanges(ByVal depthMktDataDescriptions As TWSLib.IDepthMktDataDescriptionList)
    On Error Resume Next
    MarketDepth.MktDepthExchanges depthMktDataDescriptions
End Sub

'-----------------------------
' tick-by-tick all last
'-----------------------------
Private Sub m_Tws_tickByTickAllLast(ByVal reqId As Long, ByVal tickType As Long, ByVal time As String, ByVal price As Double, ByVal size As Long, ByVal tickAttribLast As TWSLib.ITickAttribLast, ByVal exchange As String, ByVal specialConditions As String)
    On Error Resume Next
    TickByTick.TickByTickAllLast reqId, tickType, time, price, size, tickAttribLast, exchange, specialConditions
End Sub

'-----------------------------
' tick-by-tick bid ask
'-----------------------------
Private Sub m_Tws_tickByTickBidAsk(ByVal reqId As Long, ByVal time As String, ByVal bidPrice As Double, ByVal askPrice As Double, ByVal bidSize As Long, ByVal askSize As Long, ByVal tickAttribBidAsk As TWSLib.ITickAttribBidAsk)
    On Error Resume Next
    TickByTick.TickByTickBidAsk reqId, time, bidPrice, askPrice, bidSize, askSize, tickAttribBidAsk
End Sub

'-----------------------------
' tick-by-tick midpoint
'-----------------------------
Private Sub m_Tws_tickByTickMidPoint(ByVal reqId As Long, ByVal time As String, ByVal midPoint As Double)
    On Error Resume Next
    TickByTick.TickByTickMidPoint reqId, time, midPoint
End Sub

'-----------------------------
' historical ticks last
'-----------------------------
Private Sub m_Tws_historicalTicksLast(ByVal reqId As Long, ByVal ticks As TWSLib.IHistoricalTickLastList, ByVal done As Boolean)
    On Error Resume Next
    If Not ticks Is Nothing Then
        HistoricalData.UpdateHistoricalTicksLast reqId, ticks, done
    End If
End Sub

'-----------------------------
' historical ticks bid/ask
'-----------------------------
Private Sub m_Tws_historicalTicksBidAsk(ByVal reqId As Long, ByVal ticks As TWSLib.IHistoricalTickBidAskList, ByVal done As Boolean)
    On Error Resume Next
    If Not ticks Is Nothing Then
        HistoricalData.UpdateHistoricalTicksBidAsk reqId, ticks, done
    End If
End Sub

'-----------------------------
' historical ticks
'-----------------------------
Private Sub m_Tws_historicalTicks(ByVal reqId As Long, ByVal ticks As TWSLib.IHistoricalTickList, ByVal done As Boolean)
    On Error Resume Next
    If Not ticks Is Nothing Then
        HistoricalData.UpdateHistoricalTicks reqId, ticks, done
    End If

End Sub

'-----------------------------
' completed order
'-----------------------------
Private Sub m_Tws_completedOrder(ByVal contract As TWSLib.IContract, ByVal order As TWSLib.IOrder, ByVal orderState As TWSLib.IOrderState)
    On Error Resume Next
    CompletedOrders.UpdateCompletedOrder contract, order, orderState
End Sub


